/*
 *
 AUFGABENSTELLUNG:
 * [X] = erl.
 * [?] = nachlesen
 * [ ] = nicht erl.
 *
        Es soll ein rudimentärer HTTP 1.1-Server entwickelt werden welcher folgenden Anforderungen genügt:
    [ ] Unterstützung der GET, HEAD, POST Methode gemäß HTTP 1.0/HTTP 1.1
    [X] Unterstützungen von „persistenten“ Verbindungen nach HTTP 1.1
    [ ] Unterstützung der „100 continue“ nach HTTP 1.1
    [ ] Unterstützung von „Multihoming“
    [ ] Unterstützung von „If-Modified-Since“ und „If-Unmodified-Since“ Header
    [X] Unterstützung mehrerer paralleler Verbindungen
    [X] Konfiguration mittel Propertiedateien.
 *
 *
 *
 * If-modified-Since Erklärung:
 *
 * Das „If-Modified-Since“-Header-Feld wird von einem Client bei einer Anfrage an den Server mitgeschickt,
 wenn der Client die angeforderte Ressource bereits im Cache hat.
 Der Wert dieses Feldes wird vom Webserver so interpretiert, dass er den
 Inhalt der angeforderten Ressource nur dann zurückschicken soll, wenn diese seit dem im Feld notierten
 Zeitpunkt verändert wurde. Falls sie sich seit dem nicht geändert hat, wird der Statuscode 304
 zurückgeschickt.
 *
 * Andere gute Erklärung (unterer Teil der Seite): http://floern.com/webscripting/if-modified-since-nachbauen
 *
 * 100 Continue Erkläung:
 *
 * client sendet header mit expect: 100-continue
[10:03:03] Tobias Rausch: du parst header
[10:03:17] Tobias Rausch: wenn du alles unterstützt, was er anfragt schickst du nen 100-continue
[10:03:27] Tobias Rausch: dann schickt dir client die daten vom request
 */

package webserver;

import java.io.*;
import java.text.*;
import java.util.*;

/**
 *
 * @author Peter
 * Manage Protokoll communications, builds HTTP headers and build errorcodes
 * when clients ask stupid things.
 */
public class Handler_old {

	String received;
        byte[] response;      //Rückgabe an Daniel
	Boolean versionSwitch, keepAliveSwitch, errorState;
        String serverInfo;
        String httpStatus;
        String httpMethod;
        String httpParameters;

        SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");

        FileManager fm;

	/**
         * receives the response string of clients
         * and copy it to local string + get ServerVersion from Serverclass
         * @param datas
         */

	public Handler_old(String datas)
	{
                serverInfo = Server.getInstance().getServerName() + " " + Server.getInstance().getServerVersion();
		received = datas;                   //copy datas for class
                httpStatus = "";
                httpMethod = "";

                String log_request = received.substring(0, received.indexOf("HTTP"));
                log_request = log_request.trim();
                Logging.getInstance().log("(INFO) Received request: "+log_request);
	}

        /**
        * check for Headerversion, Check for errors, check if connection should keep alive.
        * In errorcase only send Headerinformation with errorcode to client.
        * Generate new object of file
        *
         * @return
         */

        public byte[] DoSomething() {

            byte[] headerBytes;
            byte[] responseBytes;
            byte[] fileBytes;

            setHTTPMethodAndParameters();                        // set method of http request (GET, POST,...)
            CheckProtokoll();                       //check for Protokoll
            CheckForErrors();                       //check for errors
            CheckConnectionState();


            if (errorState)                         //in errorcase
            {
                headerBytes = GenerateHTTPHeader().getBytes();
                return headerBytes;
            }

            if(httpMethod.equals("HEAD")) { // only header is sent
                headerBytes = GenerateHTTPHeader().getBytes();
                return headerBytes;
            }

            fm = new FileManager(GetPath());                                        //objekt von freddy
            fileBytes = fm.readFile();                                       //lese www Seite
            httpStatus = fm.getErrorCode(); //errorcode für header
            headerBytes = GenerateHTTPHeader().getBytes();                   //generiere Header bytes
            responseBytes = new byte[fileBytes.length + headerBytes.length]; //Antwort in byte array länge festlegen

            System.arraycopy(headerBytes, 0, responseBytes, 0, headerBytes.length); //kopiere header in array

            if(httpMethod.equals("GET")) {
                System.arraycopy(fileBytes, 0, responseBytes, headerBytes.length, fileBytes.length);
            }
            else if(httpMethod.equals("POST")) {
                // build date?!
                System.arraycopy(fileBytes, 0, responseBytes, headerBytes.length, fileBytes.length);
            }

            return responseBytes;

        }

        private String GetPath()
        {
            String path = "";
            String array_path[];
            String firstLine = received.substring(0, received.indexOf(System.getProperty("line.separator"))).trim();

            if(firstLine.contains("?")) { // parameter gefunden
                array_path = firstLine.substring(4).split(" ");
                path = array_path[0].substring(1, array_path[0].indexOf("?"));
            }
            else { // keine parameter
                array_path = firstLine.substring(4).split(" ");
                path = array_path[0].substring(1).trim();
            }

            return path;
        }

	//Response zum GET Request
	private String GenerateHTTPHeader()
	{
            String answer = new String();

            if (versionSwitch)
                answer = answer + "HTTP/1.1 " + httpStatus + "\r\n";                                /*HTTPvers*/
            else
                answer = answer + "HTTP/1.0 " + httpStatus + "\r\n";                                /*HTTPvers*/

            answer = answer + "Date: "+ getCurrentDate() +"\r\n";                   /*Date*/
            answer = answer + "Server: "+serverInfo + "\r\n";                       /*Server*/
            if (httpStatus.contains("200"))
                answer = answer + "Last-Modified: " + dateFormat.format(fm.getLastModified()) + "\r\n";
            answer = answer + "Content-Length: "+fm.getContentLength()+"\r\n";      /*länge*/       //freddy int
            answer = answer + "Content-Type: "+fm.getMIMEType()+"\r\n";             /*type*/        //freddy string "text/html"

            if (keepAliveSwitch)
                answer = answer + "Connection: keep-alive\r\n\n";                            /*connection*/  //ich
            else
                answer = answer + "Connection: close\r\n\n";                            /*connection*/  //ich

            String log_response = answer.substring(0, answer.indexOf("Date: ")-1);
            Logging.getInstance().log("(INFO) Response with: "+log_response);

            return answer;                                                          //rückgabe Antwort str
	}

        private String getCurrentDate() {
            Date currentDate = new Date();                                          //neues Datum
            dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");        //hole date
            return dateFormat.format(currentDate);                                  //rückgabe Datum

        }

        /**
         *
         * @return
         */
        public boolean GetKeepAlive()
        {
            return versionSwitch;                                                           //rückgabe für Daniel
        }

        private void CheckProtokoll()
        {
            if (received.contains("HTTP/1.1"))
                versionSwitch = true;
            else
                versionSwitch = false;
        }

        private void CheckConnectionState()
        {
            if (received.contains("keep-alive") && versionSwitch)
                keepAliveSwitch = true;
            else
                keepAliveSwitch = false;
        }

        private void CheckForErrors()                   //Fehlerkontrolle
        {
            //400 Fehlerhafter Request
            //501 not implemented
            //505 http Vers. not implemented
            //100 Continue
            errorState = false;

            if (received.contains("HTTP/0.9")) {
                errorState = true;
                httpStatus = "505 HTTP Version not supported";
            }
            else if(received.contains("Expect: 100-continue") && Server.getInstance().getContinueSupportStatus()) {

                // TODO abfrage, ob alles unterstützt wird, was im header geschickt wird...
                errorState = true;
                httpStatus = "100 Continue";
            }

        }

        /**
         *
         */
        public void setHTTPMethodAndParameters() {

            String firstLine = received.substring(0, received.indexOf(System.getProperty("line.separator"))).trim();
            String[] param;
            String param_str;

            if(firstLine.startsWith("GET")) {
                httpMethod = "GET";

                param = firstLine.substring(4).split(" ");
                param_str = param[0].substring(param[0].indexOf("?")+1);

                httpParameters = param_str;

                Logging.getInstance().log("(INFO) GET-Parameters: "+httpParameters);

                return;
            }

            if(firstLine.startsWith("POST")) {
                httpMethod = "POST";

                String breakLine = System.getProperty("line.separator")+System.getProperty("line.separator");
                param_str = received.substring(received.indexOf(breakLine)).trim();

                httpParameters = param_str;

                Logging.getInstance().log("(INFO) POST-Parameters: "+httpParameters);

                return;
            }

            if(firstLine.startsWith("HEAD")) {
                httpMethod = "HEAD";

                httpParameters = "";

                return;
            }

            else {
                errorState = true;
                httpStatus = "501 Not Implemented";
            }

            Logging.getInstance().log("(ERROR) Could not find a valid HTTP-Method in \""+firstLine+"\"");


        }

}